package cn.lngaosu.lwyd.module.integration.service.apptoken;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.Header;
import cn.lngaosu.lwyd.framework.common.pojo.PageResult;
import cn.lngaosu.lwyd.framework.common.util.http.HttpUtils;
import cn.lngaosu.lwyd.framework.common.util.json.JsonUtils;
import cn.lngaosu.lwyd.framework.common.util.object.BeanUtils;
import cn.lngaosu.lwyd.module.infra.service.config.ConfigService;
import cn.lngaosu.lwyd.module.integration.controller.admin.weixinusernum.vo.WeixinUserNumPageReqVO;
import cn.lngaosu.lwyd.module.integration.controller.admin.weixinusernum.vo.WeixinUserNumSaveReqVO;
import cn.lngaosu.lwyd.module.integration.dal.dataobject.weixinusernum.WeixinUserNumDO;
import cn.lngaosu.lwyd.module.integration.dal.mysql.weixinusernum.WeixinUserNumMapper;
import cn.lngaosu.lwyd.module.integration.service.weixinusernum.WeixinUserNumService;
import cn.lngaosu.lwyd.module.integration.util.WeiboUtil;
import cn.lngaosu.lwyd.module.integration.util.WeiboUtil2;
import cn.lngaosu.lwyd.module.system.dal.dataobject.webinterfacelog.WebinterfaceLogDO;
import cn.lngaosu.lwyd.module.system.dal.mysql.webinterfacelog.WebinterfaceLogMapper;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static cn.lngaosu.lwyd.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.lngaosu.lwyd.module.integration.enums.ErrorCodeConstants.WEIXIN_USER_NUM_NOT_EXISTS;

/**
 * 获取平台token Service 实现类
 *
 * @author 张恒
 */
@Service
@Validated
public class AppTokenServiceImpl implements AppTokenService {
    private static final Logger logger = LoggerFactory.getLogger(AppTokenServiceImpl.class);

    @Resource
    private ConfigService configService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private WebinterfaceLogMapper webinterfaceLogMapper;


    @Override
    public String getWeixinToken() {
        // 接口配置
        String configValue = configService.getConfigValueByKey("weixinConfig");
        if (StringUtils.isEmpty(configValue)) {
            return null;
        }

        JSONObject configJo = JSONObject.parseObject(configValue);
        // 接口开关
        String onOff = configJo.getString("onOff");
        if (!"on".equals(onOff)) {
            return null;
        }

        String token = stringRedisTemplate.opsForValue().get("token:weixin");

        if (StringUtils.isNotEmpty(token)) {
            return token;
        }

        // 请求地址
        String tokenUrl = configJo.getString("tokenUrl");

        // 初始化日志数据（默认成功）
        WebinterfaceLogDO webinterfaceLogDO = new WebinterfaceLogDO();
        webinterfaceLogDO.setInterfaceSystemName("微信公众号");
        webinterfaceLogDO.setInterfaceName("获取token");
        webinterfaceLogDO.setInterfaceUrl(tokenUrl);
        webinterfaceLogDO.setInterfaceRequestMethod("GET");
        webinterfaceLogDO.setInterfaceParam(null);
        webinterfaceLogDO.setInterfaceStatus("成功");
        webinterfaceLogMapper.insert(webinterfaceLogDO);

        try {
            String result = HttpUtils.get(tokenUrl, new HashMap<>());

            // 解析接口结果
            JSONObject resultJo = JSONObject.parseObject(result);
            String status = resultJo.getString("status");
            if (!"00".equals(status)) {
                webinterfaceLogDO.setInterfaceStatus("失败");
                webinterfaceLogDO.setInterfaceErrorInfo(result);
                webinterfaceLogMapper.updateById(webinterfaceLogDO);
            }
            JSONObject dataJo = resultJo.getJSONObject("data");
            token = dataJo.getString("AccessTokenKey");
            stringRedisTemplate.opsForValue().set("token:weixin", token, 1800L, TimeUnit.SECONDS);
        } catch (Exception e) {
            webinterfaceLogDO.setInterfaceStatus("失败");
            webinterfaceLogDO.setInterfaceErrorInfo(e.getMessage());
            webinterfaceLogMapper.updateById(webinterfaceLogDO);
            logger.error("微信公众号【获取token】接口调用失败！", e);
        }

        return token;
    }

    @Override
    public String getWeixinVideoToken() {
        // 接口配置
        String configValue = configService.getConfigValueByKey("weixinVideoConfig");
        if (StringUtils.isEmpty(configValue)) {
            return null;
        }

        JSONObject configJo = JSONObject.parseObject(configValue);
        // 接口开关
        String onOff = configJo.getString("onOff");
        if (!"on".equals(onOff)) {
            return null;
        }

        String token = stringRedisTemplate.opsForValue().get("token:weixinVideo");

        if (StringUtils.isNotEmpty(token)) {
            return token;
        }

        // 接口配置信息
        String appid = configJo.getString("appid");
        String secret = configJo.getString("secret");
        String tokenUrl = configJo.getString("tokenUrl");
        tokenUrl = tokenUrl + "?grant_type=client_credential&appid="+ appid +"&secret=" + secret;

        // 初始化日志数据（默认成功）
        WebinterfaceLogDO webinterfaceLogDO = new WebinterfaceLogDO();
        webinterfaceLogDO.setInterfaceSystemName("微信视频号");
        webinterfaceLogDO.setInterfaceName("获取token");
        webinterfaceLogDO.setInterfaceUrl(tokenUrl);
        webinterfaceLogDO.setInterfaceRequestMethod("GET");
        webinterfaceLogDO.setInterfaceParam(null);
        webinterfaceLogDO.setInterfaceStatus("成功");
        webinterfaceLogMapper.insert(webinterfaceLogDO);

        try {
            String result = HttpUtils.get(tokenUrl, new HashMap<>());

            // 解析接口结果
            JSONObject resultJo = JSONObject.parseObject(result);
            Integer errcode = resultJo.getInteger("errcode");
            if (ObjectUtils.isNotEmpty(errcode)) {
                webinterfaceLogDO.setInterfaceStatus("失败");
                webinterfaceLogDO.setInterfaceErrorInfo(result);
                webinterfaceLogMapper.updateById(webinterfaceLogDO);
            }
            token = resultJo.getString("access_token");
            stringRedisTemplate.opsForValue().set("token:weixinVideo", token, 7000L, TimeUnit.SECONDS);
        } catch (Exception e) {
            webinterfaceLogDO.setInterfaceStatus("失败");
            webinterfaceLogDO.setInterfaceErrorInfo(e.getMessage());
            webinterfaceLogMapper.updateById(webinterfaceLogDO);
            logger.error("微信视频号【获取token】接口调用失败！", e);
        }

        return token;
    }

    @Override
    public String getWeiboToken() {
        // 接口配置
        String configValue = configService.getConfigValueByKey("weiboConfig");

        if (StringUtils.isEmpty(configValue)) {
            return null;
        }

        JSONObject configJo = JSONObject.parseObject(configValue);
        // 接口开关
        String onOff = configJo.getString("onOff");
        if (!"on".equals(onOff)) {
            return null;
        }

        String token = stringRedisTemplate.opsForValue().get("token:weibo");

        if (StringUtils.isNotEmpty(token)) {
            return token;
        }

        // 接口配置信息
        String userId = configJo.getString("userId");
        String passwd = configJo.getString("passwd");
        String clientId = configJo.getString("clientId");
        String clientSecret = configJo.getString("clientSecret");
        String redirectUri = configJo.getString("redirectUri");
        String authorizeUrl = configJo.getString("authorizeUrl");
        String accessTokenUrl = configJo.getString("accessTokenUrl");
        String code = configJo.getString("code");

        // 构造请求参数
        JSONObject params = new JSONObject();
        params.put("client_id", clientId);
        params.put("client_secret", clientSecret);
        params.put("grant_type", "authorization_code");
        params.put("code", code);
        params.put("redirect_uri", redirectUri);

        // 初始化日志数据（默认成功）
        WebinterfaceLogDO webinterfaceLogDO = new WebinterfaceLogDO();
        webinterfaceLogDO.setInterfaceSystemName("微博");
        webinterfaceLogDO.setInterfaceName("获取access_token接口");
        webinterfaceLogDO.setInterfaceUrl(accessTokenUrl);
        webinterfaceLogDO.setInterfaceRequestMethod("POST");
        webinterfaceLogDO.setInterfaceParam(JSONObject.toJSONString(params));
        webinterfaceLogDO.setInterfaceStatus("成功");
        webinterfaceLogMapper.insert(webinterfaceLogDO);

        try {
            // 构造请求头数据
            Map<String, String> headerMap = new HashMap<>();
            headerMap.put(Header.CONTENT_TYPE.getValue(), "application/x-www-form-urlencoded");
            // 处理请求体数据
            List<String> bodyStrList = new ArrayList<>();
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                String tempStr = entry.getKey() + "=" + entry.getValue().toString();
                bodyStrList.add(tempStr);
            }
            String bodyStr = bodyStrList.stream().collect(Collectors.joining("&"));

            String result = HttpUtils.post(accessTokenUrl, headerMap, bodyStr);

            // 解析接口结果
            JSONObject resultJo = JSONObject.parseObject(result);
            Integer errcode = resultJo.getInteger("error_code");
            if (ObjectUtils.isNotEmpty(errcode)) {
                webinterfaceLogDO.setInterfaceStatus("失败");
                webinterfaceLogDO.setInterfaceErrorInfo(result);
                webinterfaceLogMapper.updateById(webinterfaceLogDO);
            }
            token = resultJo.getString("access_token");
            String uid = resultJo.getString("uid");
            stringRedisTemplate.opsForValue().set("token:weibo", token, 2637000L, TimeUnit.SECONDS);
            stringRedisTemplate.opsForValue().set("weiboUid", uid);
        } catch (Exception e) {
            webinterfaceLogDO.setInterfaceStatus("失败");
            webinterfaceLogDO.setInterfaceErrorInfo(e.getMessage());
            webinterfaceLogMapper.updateById(webinterfaceLogDO);
            logger.error("微博【获取token】接口调用失败！", e);
        }

        return token;
    }
}